package com.song.boot.springstudy.netty.fileregion;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;

import java.io.FileOutputStream;
import java.io.OutputStream;
//Netty 零拷贝文件传输案例：FileRegion vs 传统堆内存复制
public class FileClient {

    static final boolean SSL = System.getProperty("ssl") != null;
    static final String HOST = System.getProperty("host", "127.0.0.1");
    static final int PORT = Integer.parseInt(System.getProperty("port", SSL? "8992" : "8023"));
    static final String OUTPUT_PATH = System.getProperty("output", "received_file.dat");

    public static void main(String[] args) throws Exception {
        // 配置SSL
        final SslContext sslCtx;
        if (SSL) {
            sslCtx = SslContextBuilder.forClient()
                .trustManager(InsecureTrustManagerFactory.INSTANCE).build();
        } else {
            sslCtx = null;
        }

        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
             .channel(NioSocketChannel.class)
             .handler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 protected void initChannel(SocketChannel ch) throws Exception {
                     ChannelPipeline p = ch.pipeline();
                     if (sslCtx != null) {
                         p.addLast(sslCtx.newHandler(ch.alloc(), HOST, PORT));
                     }
                     p.addLast(
                             new StringEncoder(),
                             new LineBasedFrameDecoder(8192),
                             new StringDecoder(),
                             new FileClientHandler());
                 }
             });

            ChannelFuture f = b.connect(HOST, PORT).sync();
            
            // 发送请求获取文件
            f.channel().writeAndFlush("get_file");
            
            f.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully();
        }
    }

    public static class FileClientHandler extends SimpleChannelInboundHandler<String> {
        private OutputStream out;
        private long bytesReceived;

        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            out = new FileOutputStream(OUTPUT_PATH);
            System.out.println("准备接收文件...");
        }

        @Override
        protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
            // 这里实际上应该处理字节数据，但为了示例简化，我们假设收到的是字符串
            // 实际应用中应该使用ByteBuf处理二进制数据
            out.write(msg.getBytes());
            bytesReceived += msg.length();
            System.out.println("已接收: " + bytesReceived + " bytes");
        }

        @Override
        public void channelInactive(ChannelHandlerContext ctx) throws Exception {
            out.close();
            System.out.println("文件接收完成");
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            cause.printStackTrace();
            ctx.close();
        }
    }
}